package com.ojoin.trade.common.utils;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.apache.commons.beanutils.BeanMap;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;

/**
 * 对Bean进行操作的相关工具方法
 *
 */
public class BeanMapUtils {
	/**
	 * 将Bean对象转换成Map对象，将忽略掉值为null或size=0的属性
	 * @param obj 对象
	 * @return 若给定对象为null则返回size=0的map对象
	 */
	public static Map<String, Object> toMap(Object obj) {
		Map<String, Object> map = new HashMap<String, Object>();
		if (obj == null) {
			return map;
		}
		BeanMap beanMap = new BeanMap(obj);
		Iterator<String> it = beanMap.keyIterator();
		while (it.hasNext()) {
			String name = it.next();
			Object value = beanMap.get(name);
			// 转换时会将类名也转换成属性，此处去掉
			if (value != null && !name.equals("class")) {
				map.put(name, value);
			}
		}
		return map;
	}
	
	/**
	 * 将Bean对象转换成Map对象，将忽略掉值为null或size=0的属性
	 * @param prefix 追加key的前缀
	 * @param obj 对象
	 * @return 若给定对象为null则返回size=0的map对象
	 */
	public static Map<String, Object> toMap(String prefix,Object obj) {
		Map<String, Object> map = new HashMap<String, Object>();
		if (obj == null) {
			return map;
		}
		BeanMap beanMap = new BeanMap(obj);
		Iterator<String> it = beanMap.keyIterator();
		while (it.hasNext()) {
			String name = it.next();
			Object value = beanMap.get(name);
			// 转换时会将类名也转换成属性，此处去掉
			if (value != null && !name.equals("class")) {
				if(StringUtils.isNotEmpty(prefix)){
					map.put(prefix+name, value);
				}else {
					map.put(name, value);
				}
			}
		}
		return map;
	}

	/**
	 * 该方法将给定的所有对象参数列表转换合并生成一个Map，对于同名属性，依次由后面替换前面的对象属性
	 * @param objs 对象列表
	 * @return 对于值为null的对象将忽略掉
	 */
	public static Map<String, Object> toMap(Object... objs) {
		Map<String, Object> map = new HashMap<String, Object>();
		for (Object object : objs) {
			if (object != null) {
				map.putAll(toMap(object));
			}
		}
		return map;
	}
	
	 /** 
     * Converts a map to a JavaBean. 
     *  
     * @param type type to convert 
     * @param map map to convert 
     * @return JavaBean converted 
     * @throws IntrospectionException failed to get class fields 
     * @throws IllegalAccessException failed to instant JavaBean 
     * @throws InstantiationException failed to instant JavaBean 
     * @throws InvocationTargetException failed to call setters 
     */  
    public static final Object toBean(Class<?> type, Map<String, ? extends Object> map)   
            throws IntrospectionException, IllegalAccessException,  InstantiationException, InvocationTargetException {  
        BeanInfo beanInfo = Introspector.getBeanInfo(type);  
        Object obj = type.newInstance();  
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();  
        for (int i = 0; i< propertyDescriptors.length; i++) {  
            PropertyDescriptor descriptor = propertyDescriptors[i];  
            String propertyName = descriptor.getName();  
            if (map.containsKey(propertyName)) {  
                Object value = map.get(propertyName);  
                Object[] args = new Object[1];  
                args[0] = value;  
                descriptor.getWriteMethod().invoke(obj, args);  
            }  
        }  
        return obj;  
    }  

	/**
	 * 获取接口的泛型类型，如果不存在则返回null
	 * @param clazz
	 * @return
	 */
	public static Class<?> getGenericClass(Class<?> clazz) {
		Type t = clazz.getGenericSuperclass();
		if (t instanceof ParameterizedType) {
			Type[] p = ((ParameterizedType) t).getActualTypeArguments();
			return ((Class<?>) p[0]);
		}
		return null;
	}
	
	public static String getString(Object object) {
		try {
			if (null == object) {
				return null;
			} else {
				// 获取此类所有声明的字段
				Field[] field = object.getClass().getDeclaredFields();
				// 用来拼接所需保存的字符串
				StringBuffer sb = new StringBuffer();
				// 循环此字段数组，获取属性的值
				for (int i = 0; i < field.length && field.length > 0; i++) {
					// 值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查.
					field[i].setAccessible(true);
					// field[i].getName() 获取此字段的名称
					// field[i].get(object) 获取指定对象上此字段的值
					if (i == field.length - 1) {
						sb.append(field[i].getName() + ": "
								+ field[i].get(object) + ".");
					} else {
						sb.append(field[i].getName() + ": "
								+ field[i].get(object) + ", ");
					}
				}
				return sb.toString();
			}
		} catch (SecurityException e) {
			e.printStackTrace();
			return null;
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
			return null;
		} catch (IllegalAccessException e) {
			e.printStackTrace();
			return null;
		}
	}
	
	/**
     * 创建Mock 实例
     * @param clazz
     * @param excludeFieldNames
     * @return
     */
    public static Map getProperties(Class clazz, String... excludeFieldNames) {  
        Map ret = new HashMap();  
        try {  
            BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();  
            for (PropertyDescriptor descriptor : propertyDescriptors) {  
                if ("class".equals(descriptor.getName()) || ArrayUtils.contains(excludeFieldNames, descriptor.getName())) {  
                    continue;
                }  
                if (BeanUtils.isSimpleValueType(descriptor.getPropertyType())) {  
                	ret.put(descriptor.getName(), descriptor.getPropertyType()); 
                }  
            }  
        } catch (Exception e) {  
        }  
        return ret;  
    }
}